﻿/**	\file		lxpref.h
 *	\date		(2014-11-17 23:27:30)/(2014-11-17 23:59:16)
 *-----------------------------------------------------------------------------
 *	\brief
 *	\version	1.0.0.1
 *	\author		Nick Shallery	(nicknide@gmail.com)
 *	\copyright	YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.
 *-----------------------------------------------------------------------------
**/

#if			!defined(__LOLIX__PROFILE__LX_PREF__H__NICK__K_IN_G__)
#define		__LOLIX__PROFILE__LX_PREF__H__NICK__K_IN_G__


#if			!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)
	#include	<lolix/lolix_macro.h>
#endif	//	!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)

#if			!defined(__LOLIX__LOLIX_TYPE__K_IN_G__)
	#include	<lolix/lolix_type.h>
#endif	//	!defined(__LOLIX__LOLIX_TYPE__K_IN_G__)

#if			!defined(__LOLIX__LOLIX_INSTANCE__K_IN_G__)
	#include	<lolix/lolix_inst.h>
#endif	//	!defined(__LOLIX__LOLIX_INSTANCE__K_IN_G__)

#if			!defined(__LOLIX__LOLI__THREAD__NICK__K_IN_G__)
	#include	<lolix/loli/thread.h>
#endif	//	!defined(__LOLIX__LOLI__THREAD__NICK__K_IN_G__)

#if			!defined(__LOLIX__TOY__ALIGN__HPP__NICK__K_IN_G__)
	#include	<lolix/toy/align.hpp>
#endif	//	!defined(__LOLIX__TOY__ALIGN__HPP__NICK__K_IN_G__)

#if			!defined(__LOLIX__TOY__TIME_TYPES__K_IN_G__)
	#include	<lolix/toy/time_types.h>
#endif	//	!defined(__LOLIX__TOY__TIME_TYPES__K_IN_G__)


#if			!defined(__LOLIX__LXIO__LXIO_ASYNC_POOL__H__NICK__K_IN_G__)
	#include	<lxio/lxio_async_pool.h>
#endif	//	!defined(__LOLIX__LXIO__LXIO_ASYNC_POOL__H__NICK__K_IN_G__)

namespace lolix{namespace loli{class signal;}}

namespace lxpref
{
enum LXPROFILE_EVENT_FLAG LOLIX_ETYPE(lolix::lx_u32)
{
#define		LX_PREF_DEF__EVENT(name, rtv, have_str_param)	name = rtv,
#define		LX_PREF_DEF__EVENT_END(name) name
#include	"./_lxpref_event_types.inl"
#undef		LX_PREF_DEF__EVENT
#undef		LX_PREF_DEF__EVENT_END
};


template<lolix::lx_u32 _HaveStr>
class section_had_name{enum{is_have_name = false};};
#define		LX_PREF_DEF__EVENT(name, rtv, have_str_param)	\
	template<> class section_had_name<name>{enum{is_have_name = have_str_param};};
#include	"./_lxpref_event_types.inl"
#undef		LX_PREF_DEF__EVENT

struct event_info
{
	lolix::lx_u64	enter_time_tick;	//	性能分析的进入时间
	lolix::lx_u64	leave_time_tick;	//	性能分析函数离开的时间（于enter_time_tick差值为性能分析内部开销)
	lolix::lx_wchar const* str_param[lolix::toy::size_info<_EVENT_FLAG_END>::size_bits];	//	性能分析所需要的字符串参数
	lolix::lx_u32	thread_id;	//	当前的线程ID
	lolix::lx_u32	section_type : lolix::toy::size_info<_EVENT_FLAG_END>::size_bits;	//	当前的参数
	lolix::lx_u32	param_cnt : lolix::toy::size_info<lolix::toy::size_info<_EVENT_FLAG_END>::size_bits>::size_bits;
};

/**
 * \brief 分析器
**/
class LOLIX_NO_VTABLE lxprofile
	: public lolix::itf
{
	LOLIX_DECLARE_ITF(lxpref::lxprofile, lolix::itf, (0x18b7ca26, 0xea34496d, 0xa7fe721d, 0x79542d1e));
public:
	/**
	 * \fn void lxprofile::touch(lolix::lx_u32 eventFlag, size_type praram_count, const lolix::lx_wchar** param_arr);
	 *
	 * \brief 记录一个分析节点.
	 *
	 * \param eventFlag 事件内容(LXPROFILE_EVENT_FLAG 的组合).
	 *
	 * \param param_count 参数个数.
	 *
	 * \param [in] param_arr 参数数组.
	 *
	**/
	LOLIX_INTERFACE(touch, void, (lolix::lx_u32 eventFlag, size_type param_count, const lolix::lx_wchar** param_arr));

	/**
	 * \fn const lolix::lx_wchar* lxprofile::new_string(const lolix::lx_wchar* name)const;
	 *
	 * \brief 通过一个字符串创建一个新字符串，新字符串不会自动释放，地址固定.
	 *
	 * \param [in] name 字符串的内容
	 *
	 * \return 返回的固定地址的字符串
	 *
	**/
	LOLIX_INTERFACE(new_string, const lolix::lx_wchar*, (const lolix::lx_wchar* name)const);

	/**
	 * \fn void lxprofile::free_string(const lolix::lx_wchar* name)const;
	 *
	 * \brief 释放一个存在的字符常量
	 *
	 * \param [in] name 需要释放的字符串地址
	 *
	**/
	LOLIX_INTERFACE(free_string, void, (const lolix::lx_wchar* name)const);


	/**
	 * \fn LOLIX_RETNV lxprofile::peed_node(event_info** evt_info);
	 *
	 * \brief 抓取一个事件
	 *
	 * \param [out] evt_info 抓取的事件的指针
	 *
	 * \return 有数据返回 LOLIX_RETURN_OK, 没有数据返回 LOLIX_INFO_LOST_SYNC
	 *
	 * \notice 返回的事件指针需要使用 free_node 销毁
	**/
	LOLIX_INTERFACE(peek_node, LOLIX_RETNV, (event_info** evt_info));

	/**
	 * \fn LOLIX_RETNV lxprofile::free_node(event_info* evt_info);
	 *
	 * \brief 销毁一个 peed 出来的事件
	 *
	 * \param [in] evt_info 需要销毁的事件
	 *
	 * \return 成功则返回LOLIX_RETURN_OK 或其它非 ERROR 消息
	**/
	LOLIX_INTERFACE(free_node, LOLIX_RETNV, (event_info* evt_info));

	/**
	 * \fn LOLIX_RETNV lxprofile::wait_node(lolix::toy::time_span const* ts)const;
	 *
	 * \brief 等待，直到有新的节点
	 *
	 * \param ts	需要等待的时间
	 *
	 * \return	成功返回LOLIX_RETNV_OK 或其它非ERROR消息，其中超时会返回 LOLIX_INFO_WAIT_TIMEOUT
	**/
	LOLIX_INTERFACE(wait_node, LOLIX_RETNV, (lolix::toy::time_span const* ts)const);

	/**
	 * \fn LOLIX_RETNV lxpofile::query_signal(lolix::loli::signal** out_signal);
	 *
	 * \brief	得到内部的信号
	 *
	 * \param [out] sign	得到所返回的信号
	 *
	 * \return 成功返回非 LOLIX_IS_ERROR, 否则返回 ERROR
	**/
	LOLIX_INTERFACE(query_signal, LOLIX_RETNV, (lolix::loli::signal** out_sign));

	template<size_type _StArrLen>
	LOLIX_INLINE_CALL void enter(LXPROFILE_EVENT_FLAG sectionType,  const lolix::lx_wchar* (&name_arr)[_StArrLen])
		{
		return this->touch(sectionType, _StArrLen, name_arr);
		}
	LOLIX_INLINE_CALL void enter(LXPROFILE_EVENT_FLAG sectionType, const lolix::lx_wchar* name)
		{
		return this->touch(sectionType, 1, &name);
		}

	LOLIX_INLINE_CALL void leave(void)
		{
		this->touch(EVENT_FLAG_ED, 0, 0);
		}
};



class LOLIX_NO_VTABLE lxpref_route_end
	: public lolix::itf
{
	LOLIX_DECLARE_ITF(lxpref::lxpref_route_end, lolix::itf, (0xf4de421b, 0x7d13432b, 0x9387b2a6, 0x21b55e0f));
public:
	LOLIX_INTERFACE(close	, LOLIX_RETNV	, (void));
	LOLIX_INTERFACE(wait	, LOLIX_RETNV	, (lolix::toy::time_span const* ts)const);
	LOLIX_INTERFACE(top		, LOLIX_RETNV	, (event_info const** evt_inf));
	LOLIX_INTERFACE(fetch	, LOLIX_RETNV	, (event_info const* evt_inf));
};

class lxpref_route;
class LOLIX_NO_VTABLE lxpref_fac
	: public lolix::itf
{
	LOLIX_DECLARE_ITF(lxpref_fac, lolix::itf, (0xf78812d0, 0x9b0d4f29, 0xa4435e0b, 0xaac586de));
public:
	LOLIX_INTERFACE(create_inst, LOLIX_RETNV, (lxprofile** out_ptr));
	LOLIX_INTERFACE(create_inst, LOLIX_RETNV, (lxpref_route** out_ptr, lxprofile* prof));
	LOLIX_INTERFACE(create_inst, LOLIX_RETNV, (lxpref_route_end** out_ptr, lolix::lx_wchar const* path, lolix::size_type path_len, lxio::file_async_pool* async_pool));
};

}

#endif	//	!defined(__LOLIX__PROFILE__LX_PREF__H__NICK__K_IN_G__)
